package com.ai.bitcoin.service.helper;

import com.ai.bitcoin.constant.MonitorSettingConstrant;
import com.ai.bitcoin.enums.MonitorPushTemplateEnum;
import com.ai.bitcoin.enums.MonitorSwitchTypeEnum;
import com.ai.bitcoin.jpa.dao.BccBasicInfoDao;
import com.ai.bitcoin.jpa.dao.BccSubCoinDao;
import com.ai.bitcoin.jpa.entity.*;
import com.ai.bitcoin.jpa.service.BccReportMonitorConfigService;
import com.ai.bitcoin.vo.Price2BccVo;
import com.ai.bitcoin.weixin.template.MonitorReportTemplate;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.math.NumberUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @description: ${description}
 * @author: gulj
 * @create: 2018-08-11 00:35
 **/
@Component
@Slf4j
public class PushWxTemplateBizHelper {

    @Autowired
    private BccSubCoinDao bccSubCoinDao;

    @Autowired
    private BccReportMonitorConfigService reportMonitorConfigService;

    @Autowired
    private BccBasicInfoDao bccBasicInfoDao;

    /**
     * 获取订阅bccId的用户openId
     *
     * @param bccId
     * @return
     */
    public List<String> getSubscribeOUserpenId(String bccId) {
        List<BccSubCoin> bccSubCoins = bccSubCoinDao.findByBccIdAndStatus(bccId, 1);
        if (null == bccSubCoins || bccSubCoins.isEmpty()) {
            log.warn("【推送报告模板】没有查询到任何人订阅 bccId 为： {}，的币", bccId);
            return null;
        }
        return bccSubCoins.stream().map(BccSubCoin::getUserOpenId).distinct().collect(Collectors.toList());
    }


    /**
     * 订阅币和打开开关的用户的openId
     *
     * @param bccId
     * @param switchTypeEnum
     * @return
     */
    public List<String> getSubscibeBccAndSwitchOnUserOpenId(String bccId, MonitorSwitchTypeEnum switchTypeEnum) {
        // 1.订阅币的的用户
        List<String> subscribeOUserpenId = getSubscribeOUserpenId(bccId);
        if (subscribeOUserpenId == null) {
            return null;
        }
        // 2.在订阅币的用户中，看某个开关是否开启
        List<BccReportMonitorConfig> monitorConfigs = reportMonitorConfigService.getByOpenIdAndBccIdAndSwitchTypeEnum(bccId, subscribeOUserpenId, switchTypeEnum);
        if (monitorConfigs == null || monitorConfigs.isEmpty()) {
            log.warn("【订阅bccId为：{} 的用户 {}，没有一个人打开 {} 的开关】", bccId, subscribeOUserpenId, switchTypeEnum);
            return null;
        }

        List<String> subscribeAndSwitchOnUserOpenIds = monitorConfigs.stream().map(BccReportMonitorConfig::getOpenId).collect(Collectors.toList());
        log.info("【既订阅bccId为：{}，又打开开关：{}，的用户有： {} 个，分别为：{}】", bccId, switchTypeEnum, subscribeAndSwitchOnUserOpenIds.size(), subscribeAndSwitchOnUserOpenIds);

        return subscribeAndSwitchOnUserOpenIds;
    }


    // 填充模板推送参数
    public <T> Map<String, Object> fillingParamMap(int type, String bccId, String remark, String id, String openId, String exchangeName, T t) {
        // 填充模板
        Map<String, Object> paramMap = new HashMap<>();

        paramMap.put("touser", openId);

        // 简介
        String introduction = MonitorSettingConstrant.DEFAULT_INTRODUCTION;
        // 监控项目
        String monitorItem = MonitorSettingConstrant.DEFAULT_MONITOR_ITEM;
        // 监控对象
        String monitorObject = getMonitorObject(bccId);
        // 地址
        String url = MonitorSettingConstrant.DEFAULT_TEMPLATE_URL;
        switch (type) {
            //舆情
            case MonitorSettingConstrant.MONITOR_NEWS_CODE:
                BccNews bccNews = (BccNews) t;
                monitorItem = MonitorPushTemplateEnum.MONITOR_NEWS_TEMPLATE.getMonitorItem();
                introduction = MonitorPushTemplateEnum.MONITOR_NEWS_TEMPLATE.getIntroduction();
                url = MonitorPushTemplateEnum.MONITOR_NEWS_TEMPLATE.getTemplateUrl();
                break;
            //交易所公告
            case MonitorSettingConstrant.MONITOR_EXCHANGE_ANNO_CODE:
                BccAnnoInfoCrawl annoInfoCrawl = (BccAnnoInfoCrawl) t;
                remark = getRemarkByDescription(annoInfoCrawl.getDescription());
                monitorItem = MonitorPushTemplateEnum.MONITOR_EXCHANGE_ANNO_TEMPLATE.getMonitorItem();
                introduction = MonitorPushTemplateEnum.MONITOR_EXCHANGE_ANNO_TEMPLATE.getIntroduction();
                url = MonitorPushTemplateEnum.MONITOR_EXCHANGE_ANNO_TEMPLATE.getTemplateUrl();
                monitorObject = StringUtils.defaultString(exchangeName, "交易所") + "公告";
                break;
            //价格
            case MonitorSettingConstrant.MONITOR_PRICE_CODE:
                introduction = MonitorPushTemplateEnum.MONITOR_PRICE_TEMPLATE.getIntroduction();
                monitorItem = MonitorPushTemplateEnum.MONITOR_PRICE_TEMPLATE.getMonitorItem();
                url = MonitorPushTemplateEnum.MONITOR_PRICE_TEMPLATE.getTemplateUrl();
                break;
            //阀值
            case MonitorSettingConstrant.MONITOR_PRICE_THRESHHOLD_CODE:
                introduction = MonitorPushTemplateEnum.MONITOR_PRICE_THRESHHOLD_CODE.getIntroduction();
                monitorItem = MonitorPushTemplateEnum.MONITOR_PRICE_THRESHHOLD_CODE.getMonitorItem();
                url = MonitorPushTemplateEnum.MONITOR_PRICE_THRESHHOLD_CODE.getTemplateUrl();
                break;
            //暴涨暴跌
            case MonitorSettingConstrant.MONITOR_BOOM_BUST_CODE:
                introduction = MonitorPushTemplateEnum.MONITOR_BOOM_BUST_TEMPLATE.getIntroduction();
                monitorItem = MonitorPushTemplateEnum.MONITOR_BOOM_BUST_TEMPLATE.getMonitorItem();
                url = MonitorPushTemplateEnum.MONITOR_BOOM_BUST_TEMPLATE.getTemplateUrl();
                break;
            //买点和卖点
            case MonitorSettingConstrant.MONITOR_BUYER_SELLER_POINT_CODE:
                introduction = MonitorPushTemplateEnum.MONITOR_BUYER_SELLER_POINT_TEMPLATE.getIntroduction();
                monitorItem = MonitorPushTemplateEnum.MONITOR_BUYER_SELLER_POINT_TEMPLATE.getMonitorItem();
                url = MonitorPushTemplateEnum.MONITOR_BUYER_SELLER_POINT_TEMPLATE.getTemplateUrl();
                break;
            //ERC20 大金额转账
            case MonitorSettingConstrant.MONITOR_TRANSFER_BIG_MONEY_CODE:
                introduction = MonitorPushTemplateEnum.MONITORY_TRANSFER_BIG_MONEY_TEMPLATE.getIntroduction();
                monitorItem = MonitorPushTemplateEnum.MONITORY_TRANSFER_BIG_MONEY_TEMPLATE.getMonitorItem();
                url = MonitorPushTemplateEnum.MONITORY_TRANSFER_BIG_MONEY_TEMPLATE.getTemplateUrl();
        }

        // 模板地址
        paramMap.put("url", url + "?type=" + type + "&bccId=" + bccId + "&id=" + id + "&openId=" + openId);
        // 简介
        paramMap.put("first", introduction);
        // 币的名称
        paramMap.put("keyword1", monitorObject);
        // 认证套餐
        paramMap.put("keyword2", monitorItem);
        paramMap.put("remark", remark);
        return new MonitorReportTemplate().buildParameterMap(paramMap);
    }

    // 详情概要
    public String getRemarkByDescription(String description) {
        String remark = MonitorSettingConstrant.DEFAULT_REMARK;
        if (StringUtils.isNotEmpty(description)) {
            remark = description.substring(0, 50);
        }
        return remark;
    }


    public boolean checkPriceRangeValid(BccReportMonitorConfig config, Price2BccVo price2BccVo) {
        BigDecimal coinPriceMin = config.getCoinPriceMin();
        BigDecimal coinPriceMax = config.getCoinPriceMax();


        return true;
    }

    // 计算流通占比
    public String computeCirculationPercent(String bccId, String volume) {
        BccBasicInfo basicInfo = bccBasicInfoDao.findByBccId(bccId);
        if (null != basicInfo) {
            // 流通总量
            BigDecimal volumeD = BigDecimal.valueOf(NumberUtils.toDouble(volume));
            String availableSupply = basicInfo.getAvailableSupply();
            if (StringUtils.isEmpty(availableSupply)) {
                String totalSupply = basicInfo.getTotalSupply();
                if (StringUtils.isEmpty(totalSupply)) {
                    log.info("【计算流通占比失败，原因 bccId 为：{}，流通数量 和 发行总量都为空】", bccId);
                    return null;
                }
                else {
                    // TODO
                    return null;
                }
            }
            else {
                BigDecimal availableSupplyD = BigDecimal.valueOf(NumberUtils.toDouble(availableSupply));
                BigDecimal percent = volumeD.divide(availableSupplyD, 4, RoundingMode.HALF_UP).multiply(BigDecimal.valueOf(100));
                log.info("【volume:{}, availableSupplyD:{} ,volume/availableSupplyD = percent : {}%】", volume, availableSupply, percent.toString());
                return percent.toString() + "%";
            }
        }
        log.warn("【计算流通占比失败，原因 bccId 为：{}，没有查询到basicinfo对象】", bccId);
        return null;
    }

    public boolean compareErc20Threshold(String percent) {
        String percentReplace = percent.replace("%", "");
        BigDecimal percentDecimal = BigDecimal.valueOf(NumberUtils.toDouble(percentReplace));
        String ercTwoZeroPercent = StringUtils.replace(MonitorSettingConstrant.ERC_TWO_ZERO_PERCENT, "%", "");
        BigDecimal ercTwoZeroPercentDecimal = BigDecimal.valueOf(NumberUtils.toDouble(ercTwoZeroPercent));
        return percentDecimal.compareTo(ercTwoZeroPercentDecimal) > 0;
    }


    public String getMonitorObject(String bccId) {
        BccBasicInfo bccBasicInfo = bccBasicInfoDao.findByBccId(bccId);
        if (bccBasicInfo == null) {
            return null;
        }
        return StringUtils.defaultString(bccBasicInfo.getNameCn()) + "/" + StringUtils.defaultString(bccBasicInfo.getNameEn());
    }
}
